﻿/**
	@file	Block.cpp
	@date	2013/1/28
	@author	김진식(jeensig@gmail.com)
	@brief	블럭의 구현부
*/

#include "Block.h"
#include "FuncClass.h"

Block::~Block()
{
	block_.clear();
}

//

Block::Block() : lotate_(0), head_(4,2)
{
	
}

/**
	@brief		랜덤으로 모양을 잡는다.
	@remarks	랜덤으로 모양을 정한 뒤 모양의 좌표를 입력한다.
*/
void Block::RandomShape()
{
	switch((rand() % 2))
	{
		case BOX:
			shape_ = BOX;
			break;
		case LINE:
			shape_ = LINE;
			break;
	}

	std::vector<Position> dummy;
	switch(shape_)
	{
		case BOX:
			dummy.push_back(Position(0,0));
			dummy.push_back(Position(1,0));
			dummy.push_back(Position(0,-1));
			dummy.push_back(Position(1,-1));

			block_.push_back(dummy);
			break;

		case LINE:
			dummy.push_back(Position(0,0));
			dummy.push_back(Position(1,0));
			dummy.push_back(Position(2,0));
			dummy.push_back(Position(3,0));

			block_.push_back(dummy);
			dummy.clear();

			dummy.push_back(Position(0,0));
			dummy.push_back(Position(0,-1));
			dummy.push_back(Position(0,-2));
			dummy.push_back(Position(0,-3));

			block_.push_back(dummy);
			break;
	}
}

/**
	@brief		블럭의 초기화
	@remarks	모든 값을 원상복구 하고 모양을 다시 잡는다.
*/
void Block::Init()
{
	block_.clear();

	lotate_ = 0;
	head_ = Position(4,2);
	
	RandomShape();
}

/**
	@brief		블럭을 그린다.
	@remarks	블럭의 위치대로 블럭을 그린다.
*/
void Block::Render()
{
	for(int i = 0; i < 4; ++i)
	{
		FuncClass::DrawTextObject("m", block_[lotate_].at(i) + head_);
	}
}

/**
	@return		블럭의 충돌이나면1 아니면 0 초기위치였으면 2를 반환
	@brief		블럭을 최신화한다.
	@remarks	블럭의 상태를 업데이트 한다.
*/
int Block::Update()
{
	for(int i = 0; i < 4; ++i)
	{
		FuncClass::DrawTextObject(" ", block_[lotate_].at(i) + head_);
	}

	return MoveToBlock(DOWN);
}

/**
	@brief		키가 눌렸으면 행동을 취한다
	@remarks	키가 눌렸을 때의 행동으로 넘어간다.
*/
void Block::InputKey(int key)
{
	switch(key)
	{
		case VK_LEFT:
			MoveToBlock(LEFT);
			break;
		case VK_RIGHT:
			MoveToBlock(RIGHT);
			break;
		case VK_UP:
			RotateBlock();
			break;
	}
}

/**
	@return		블럭이 충돌1 없으면0 맨처음이였으면 2를 반환
	@param		direction 블럭이 움직일 방향
	@brief		블럭을 움직인다.
	@remarks	블럭을 하나씩 움직인다.
*/
int Block::MoveToBlock(DIRECTION direction ///< 움직일 방향을 넘긴다.
	)
{
	switch(direction)
	{
		case LEFT:
			head_.x_ -= 1;
			if( IsCollision() )
			{
				head_.x_ += 1;
			}
			break;
		case RIGHT:
			head_.x_ += 1;
			if( IsCollision() )
			{
				head_.x_ -= 1;
			}
			break;
		case DOWN:
			head_.y_++;
			if( IsCollision() )
			{
				head_.y_--;
				if(head_.y_ == 2)
				{
					return GAMEOVER;
				}
				Render();
				Init();

				return LINECHECK;
			}
			break;
	}
	return NONE;
}

/**
	@brief		블럭 회전
	@remarks	블럭을 회전 할 때 실행되는 함수
*/
void Block::RotateBlock()
{
	int back_shape_ = lotate_;

	switch(shape_)
	{
		case LINE:
			if(lotate_ == 0)
				lotate_ = 1;
			else
				lotate_ = 0;

			if( IsCollision() )
			{
				lotate_ = back_shape_;
			}
			break;
	}
}

/**
	@return		충돌이면 true, 아니면 false를 반환
	@brief		블럭의 충돌을 검사한다.
	@remarks	블럭의 하나하나를 검사한다.
*/
bool Block::IsCollision()
{
	Position block_1 = head_ + block_[lotate_].at(0);
	Position block_2 = head_ + block_[lotate_].at(1);
	Position block_3 = head_ + block_[lotate_].at(2);
	Position block_4 = head_ + block_[lotate_].at(3);

	if( FuncClass::GetPositionChar(block_1) != ' ')
	{
		return true;
	}
	if( FuncClass::GetPositionChar(block_2) != ' ')
	{
		return true;
	}
	if( FuncClass::GetPositionChar(block_3) != ' ')
	{
		return true;
	}
	if( FuncClass::GetPositionChar(block_4) != ' ')
	{
		return true;
	}

	return false;	
}